/*
 * Copyright (c) 2006, 2007 Sun Microsystems, Inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package org.sunspotworld.demo;

import com.sun.spot.core.resources.transducers.AnalogInputEvent;
import com.sun.spot.core.resources.transducers.Condition;
import com.sun.spot.core.resources.transducers.IAnalogInput;
import com.sun.spot.core.resources.transducers.IConditionListener;
import com.sun.spot.core.resources.transducers.ISwitch;
import com.sun.spot.core.resources.transducers.ITriColorLED;
import com.sun.spot.core.resources.transducers.LEDColor;
import com.sun.spot.core.resources.transducers.SensorEvent;
import com.sun.spot.core.util.Utils;
import com.sun.spot.edemo.EDemoBoard;
import com.sun.spot.ieee_802_15_4_radio.IEEE802_15_4Environment;
import com.sun.spot.ieee_802_15_4_radio.util.IEEEAddress;
import java.io.IOException;
import java.util.Date;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * The startApp method of this class is called by the VM to start the
 * application.
 *
 * The manifest specifies this class as MIDlet-1, which means it will
 * be selected for execution.
 */
public class SunSpotApplication extends MIDlet implements IConditionListener {
    public static final double MAX_VALUE = 3.3; //in volts
    public static final double MIN_VALUE = 0.5; //in volts
    private static final int LED_STEP_VALUE = (int)((MAX_VALUE-MIN_VALUE) / 8);
    private LEDColor displayColor = LEDColor.CYAN;
    private ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
    private IAnalogInput input = EDemoBoard.getInstance().getAnalogInputs()[EDemoBoard.A1];
    private boolean thresholdExceeded = false;
    
    /**
     * Reads scalar input on A0 and displays the value to the LEDs in terms of the MAX_VALUE field
     * Also, writes value to System.out
     */
    private void displayInput() {
        if (thresholdExceeded) {
            return;
        }
        AnalogInputEvent evt = (AnalogInputEvent)input.createSensorEvent(); //read scalar input value
        System.out.println(evt.getAnalogInput() + " taken at " + new Date(evt.getTime()) + ": " + evt.getVoltage());
        //display value on LEDs
        double value = evt.getVoltage();
        for (int i=0; i<8; i++) {
            leds[i].setColor(displayColor);
            leds[i].setOn(value>MIN_VALUE + i*LED_STEP_VALUE);
        }
    }

    private Condition checkVoltageThresholds = new Condition(input, this, 250 /*time in ms*/) {
        public boolean isMet(SensorEvent evt) {
            synchronized(input) {
                if (((AnalogInputEvent)evt).getVoltage() < MIN_VALUE || ((AnalogInputEvent)evt).getVoltage() > MAX_VALUE) {
                    return true;
                }
                return false;
            }
        }
    };
    
    protected void startApp() throws MIDletStateChangeException {
        System.out.println("Hello, world");
//        new BootloaderListener().start();   // monitor the USB (if connected) and recognize commands from host

        long ourAddr = IEEE802_15_4Environment.getIEEEAddress();
        System.out.println("Our radio address = " + IEEEAddress.toDottedHex(ourAddr));
        
        ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
        checkVoltageThresholds.start();
        while (sw1.isOpen()) {                  // done when switch is pressed
            displayInput();
            Utils.sleep(1000);                  // wait 1 second
        }
        notifyDestroyed();                      // cause the MIDlet to exit
    }
    
    protected void pauseApp() {
        // This is not currently called by the Squawk VM
    }
    
    /**
     * Called if the MIDlet is terminated by the system.
     * I.e. if startApp throws any exception other than MIDletStateChangeException,
     * if the isolate running the MIDlet is killed with Isolate.exit(), or
     * if VM.stopVM() is called.
     * 
     * It is not called if MIDlet.notifyDestroyed() was called.
     *
     * @param unconditional If true when this method is called, the MIDlet must
     *    cleanup and release all resources. If false the MIDlet may throw
     *    MIDletStateChangeException  to indicate it does not want to be destroyed
     *    at this time.
     */
    protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
        for (int i = 0; i < 8; i++) {
            leds[i].setOff();
        }
    }

    public void thresholdExceeded() {
        synchronized(input) {
            thresholdExceeded = true;
            try {
                while (input.getVoltage() > MAX_VALUE) {
                    for (int i = 0; i < 8; i++) {
                        leds[i].setColor(LEDColor.RED);
                        leds[i].setOn();
                    }
                    Utils.sleep(100);
                    for (int i = 0; i < 8; i++) {
                        leds[i].setOff();
                    }
                }
                while (input.getVoltage() < MIN_VALUE) {
                    for (int i = 0; i < 8; i++) {
                        leds[i].setColor(LEDColor.BLUE);
                        leds[i].setOn();
                    }
                    Utils.sleep(100);
                    for (int i = 0; i < 8; i++) {
                        leds[i].setOff();
                    }
                }

            } catch (IOException ex) {
                ex.printStackTrace();
            }
            thresholdExceeded = false;
        }
    }

    public void conditionMet(SensorEvent arg0, Condition arg1) {
        thresholdExceeded();
    }
}
